﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

namespace SimpleTaskSystem
{
    /// <summary>
    /// 一个任务步骤
    /// </summary>
    [Serializable]
    public class Task
    {
        public string taskName;
        /// <summary>
        /// 是否自动执行
        /// </summary>
        public bool isAutomatic = false;
        /// <summary>
        /// 是否按顺序执行
        /// </summary>
        public bool sequence = true;
        public string description;
        public List<Operation> operations = new List<Operation>();
        public delegate void TaskHandler(Task task);
        public event TaskHandler onTaskStart;
        public event TaskHandler onCompleted;
        /// <summary>
        /// 是否完成，一般只用在非顺序执行情况下
        /// </summary>
        Dictionary<Operation, bool> completedOperations = new Dictionary<Operation, bool>();

        public int currentIndex
        {
            get
            {
                return _currentIndex;
            }
        }
        int _currentIndex = -1;

        /// <summary>
        /// 初始化任务
        /// </summary>
        public void InitTask()
        {
            _currentIndex = -1;
            onCompleted = null;
            foreach (var item in operations)
            {
                completedOperations[item] = false;
            }
        }
        /// <summary>
        /// 执行
        /// </summary>
        public void Excute()
        {
            foreach (var item in operations)
            {
                if (isAutomatic)
                {
                    item.isAutomatic = isAutomatic;
                }
                if (!sequence)
                {
                    item.onCompleted += OneOperationCompleted;
                }
            }
            SetNextOperation();
        }

        public Operation GetCurrentOperation()
        {
            if (_currentIndex < 0 || _currentIndex >= operations.Count)
            {
                return null;
            }
            return operations[_currentIndex];
        }

        public Operation GetOperationByName(string operation)
        {
            foreach (var item in operations)
            {
                if (item.operationName == operation)
                {
                    return item;
                }
            }
            return null;
        }
        internal void SetCurrentOperation(string operationName)
        {
            Operation o = GetOperationByName(operationName);
            _currentIndex = operations.IndexOf(o) - 1;
            Debug.Log("设置当前操作为:" + _currentIndex);
            Excute();
        }
        void Completed()
        {
            if (onCompleted != null)
            {
                onCompleted(this);
            }
        }

        void OneOperationCompleted(Operation operation)
        {
            if (sequence)
            {
                if (currentIndex < operations.Count && operation == operations[_currentIndex])
                {
                    operations[_currentIndex].onCompleted -= OneOperationCompleted;
                }
            }
            else
            {
                if (completedOperations.ContainsKey(operation))
                {
                    completedOperations[operation] = true;
                }
            }
            SetNextOperation();
        }

        void SetNextOperation()
        {
            if (sequence)//如果为按顺序执行
            {
                _currentIndex++;
                if (_currentIndex >= operations.Count)
                {
                    Completed();
                    return;
                }
            }
            else//不按顺序执行
            {
                int next = _currentIndex;
                while (next == -1 || completedOperations[operations[next]])
                {
                    next++;
                    if (next >= operations.Count)
                    {
                        Completed();
                        return;
                    }
                }
                if (next != _currentIndex)
                {
                    _currentIndex = next;
                }
                else
                {
                    return;
                }
            }
            operations[_currentIndex].onCompleted += OneOperationCompleted;
            operations[_currentIndex].Ready();
        }
    }
}
